# Отчёт о выполнении задачи "Создание программы для управления оборудованием на теплоэлектростанции"

- [Отчёт о выполнении задачи "Создание программы для управления оборудованием на теплоэлектростанции"](#отчёт-о-выполнении-задачи-cоздание-программы-для-управления-оборудованием-на-теплоэлектростанции)
  - [Постановка задачи](#постановка-задачи)
  - [Известные ограничения и вводные условия](#известные-ограничения-и-вводные-условия)
    - [Цели и Предположения Безопасности (ЦПБ)](#цели-и-предположения-безопасности-цпб)
  - [Архитектура системы](#архитектура-системы)
    - [Компоненты](#компоненты)
    - [Алгоритм работы решения](#алгоритм-работы-решения)
    - [Описание Сценариев (последовательности выполнения операций), при которых ЦБ нарушаются](#описание-сценариев-последовательности-выполнения-операций-при-которых-цб-нарушаются)
    - [Указание "доверенных компонент" на архитектурной диаграмме.](#указание-доверенных-компонент-на-архитектурной-диаграмме)
    - [Политики безопасности](#политики-безопасности)
  - [Запуск приложения и тестов](#запуск-приложения-и-тестов)
    - [Запуск приложения](#запуск-приложения)
    - [Запуск тестов](#запуск-тестов)

## Постановка задачи
Разработать кибериммунный ПЛК который будет выполнять задачи по получению и обработке данных от датчиков, выполнению команд остановки от оператора АСУ ТП, производить обновление Прикладного программного обеспечения, изменять установки Прикладной программы.


## Известные ограничения и вводные условия
По условиям организаторов должна использоваться микросервисная архитектура и шина обмена сообщениями для реализации асинхронной работы сервисов.

### Цели и Предположения Безопасности (ЦПБ)
Цели безопасности:
1. АСУ ТП всегда получает целостные критичные данные от ПЛК
2. ПЛК выполняет только аутентичное ПП
3. Конечное оборудование всегда получает аутентичные команды
4. Только авторизованные пользователи имеют доступ к лицензии ПЛК
5. Система гарантирует обработку и доставку сигналов за конечное время 
6. Обеспечение аутентичности лицензионной роли

Предположения безопасности:
1. Физическая защита периметра обеспечена
2. Персонал ТЭЦ благонадежен
3. Технологическое оборудование (Турбина) исправное
4. Уровень устройств ввода-вывода - доверенный
5. Рассматривается экспериментальная ТЭЦ, где оператор имеет только удалённый доступ к системе управления
6. Планировщик задач - доверенный модуль

## Архитектура системы
### Изначальная архитектура:

![DFD](img/archi_case.png?raw=true "Изначальная архитектура")

### Изначальная структурная схема:

![DFD](img/struct_case.png?raw=true "Структурная схема")

### Переосмысленная архитектура (упрощенная):

![DFD](img/archi.png?raw=true "Переосмысленная архитектура (упрощенная)")

### Полная диаграмма архитектуры:

![DFD](img/arhi.png?raw=true "Полная архитектура")

### Компоненты
- **SCADA (scada)** - СКАДА система. Отправляет и принимает данные от ПЛК. 
- **Принятие данных из SCADA (scada_recevier)** - Проверяет доступные команды, отправляет на task_scheduler.
- **Прием обновления** - Поступает запрос от инженера (по специальному интерфейсу SCADA) на обновления ПП. Направляет его в менеджер обновления.
- **Отправка статуса обновления** - Отправляет статус обновления ПП или ошибку (по специальному интерфейсу SCADA) на SCADA.
- **Проверка ПП** - Сверяет прошивку которая находится в хранилище и которая идет на обновление ПП.
- **Менеджер обновления** - Оркестрирует процесс обновления и спрашивает планировщик задач о его возможности.
- **Хранилище ПП** - Хранит в себе версии прикладной программы полученные от инженера.
- **Обновление ПП** - Модуль который запускает обновление ПП.
- **Таймер** - Аналог кварцевых часов. Отправляет по запросу значение времени сейчас.
- **Планировщик задач (task_scheduler)** - Оркестратор системы. Проверяет авторизацию, срочную отправку сообщения, отправляет задачи на другие модули, получает ответы. При каждом внешнем запросе "Авторизует пользователя", вызывая модуль authorization-verifier.
- **Проверка авторизации (authorization-verifier)** - Получает данные (логин, пароль (хэш) ) о пользователе, сверяет и даёт ответ планировщику задач (при недействительных давнных) или отдаёт данные дальше на проверку (+ роль пользователя) на модуль license_verifier.
- **Проверка лицензии (license-verifier)** - Проверяет отправленный пользователем лицензионный ключ (лицензию), используя небольшой криптографический алгоритм. Результат отправляет в task_scheduler.
- **Прикладная программа** - Модуль выполнения бизнес логики. Определяет критичность аналоговых данных, следит за мощностью турбины. Имеет возможность обновления и корректировки пороговых значений для аналоговых данных. Сверяет данные при помощи блока Проверки данных.
- **Командный блок (command-block)** -  используется планировщиком для отправки сообщений и управления турбиной. Отправляет сообщения на scada-sender.
- **Отправка данных в SCADA (scada-sender)** - Модуль отправки сообщения на скаду. Получает данные от командного блока, очищает ненужные поля и отправляет в scada.
- **Проверка данных** - Сравнивает данные прищедшие из ПП и блока хранилища данных, если данные совпадают, то передает статус что их можно отправить.
- **Хранилище данных** - Является хранилищем после обработки данных датчиков. Отдает их по запросу в блок проверки.
- **Обработка дискретных данных** - Приём аналоговых данных от датчиков.
- **Обработка аналоговых данных** - Приём дискретных данных от датчиков.
- **Датчики** - Эмуляция датчиков температуры, измерения мощности и скорости работы турбины. 
- **Турбина** - Это турбина, можно подать команды на включение и выключение, передает статус в датчики о своем состоянии.

## Алгоритм работы решения
### Общая схема работы ПЛК
![DFD](img/all_scheme.png?raw=true "Общая схема работы плк")

### Обработка аналоговых данных
![DFD](img/svg/data_dat.svg?raw=true "Обработка аналоговых данных")

### Обработка дискретных данных
![DFD](img/svg/data_turb.svg?raw=true "Обработка дискретных данных")

### Остановка турбины
![DFD](img/svg/stop_turb.svg?raw=true "Остановка турбины")

### Изменение параметров ПП
![DFD](img/svg/switch_par.svg?raw=true "Изменение параметров ПП")

### Обновление ПП
![DFD](img/update.png?raw=true "Обновление ПП")

### Описание Сценариев (последовательности выполнения операций), при которых ЦБ нарушаются
1. В момент обновления прошивки происходит обработка критичных данных на ПП, что приводит к потере критичных данных что нарушает ЦБ 1 и ЦБ 5.
2. При вызове обновления и ожидания его установки происходит измение ее при хранении, что нарушает ЦБ 2.
3. Обработка данных с датчиков теряет данные при отправки их на ПП, что делает невозможным их обработку как следствие нарушение ЦБ 1, так как ПЛК не отправил данные на ACУ ТП.
4. При отправке запроса на исполнение команды остановки, блок авторизации пропускает пользователя без проверки логина и пароля, сразу на блок лицензии что нарушает ЦБ 4.
5. Происходит ошибка при измении параметров ПП что нарушает проверку критичности данных от данных, что влечет за собой нарушение ЦБ 1.
6. После проведения авторизации и передачи данных на блок лицензии, происходит искажения ключа прошивки, что приводит к опредлению неправильному определению лицензионной роли, нарушение ЦБ 6.
7. При отправки команды для отключения турбины в момент прохождения ее через ПЛК происходит изменение ее, что нарушает ЦБ 3.

**Диаграмма для первого негативного сценария**

![DFD](img/negative_scheme/1neg.png?raw=true "негативный сценарий")

**Диаграмма для второго негативного сценария**

![DFD](img/negative_scheme/2neg.png?raw=true "негативный сценарий")

**Диаграмма для третьего негативного сценария**

![DFD](img/negative_scheme/3neg.png?raw=true "негативный сценарий")

**Диаграмма для четвертого негативного сценария**

![DFD](img/negative_scheme/4neg.png?raw=true "негативный сценарий")

**Диаграмма для пятого негативного сценария**

![DFD](img/negative_scheme/5neg.png?raw=true "негативный сценарий")

**Диаграмма для шестого негативного сценария**

![DFD](img/negative_scheme/6neg.png?raw=true "негативный сценарий")

**Диаграмма для седьмого негативного сценария**

![DFD](img/negative_scheme/7neg.png?raw=true "негативный сценарий")


### Указание "доверенных компонент" на архитектурной диаграмме.

![DFD](img/sec_archi.png?raw=true "Архитектура с указанием доверенных компонентов")

### Политики безопасности 


```python {lineNo:true}
if src == 'scada-receiver' and dst == 'task-scheduler' and \
            opr in ('check_sensors', 'update_settings', \
                    'turbine_stop', 'turbine_start'):
        authorized = True
    elif src == 'task-scheduler' and dst == 'authorization-verifier':
        authorized = True
    elif src == 'task-scheduler' and dst == 'command-block' and \
            opr in ('send_message', 'turbine_stop', 'turbine_start'):
        authorized = True
    elif src == 'authorization-verifier' and dst == 'task-scheduler' and \
            (opr == 'send_message'):
        authorized = True
    elif src == 'authorization-verifier' and dst == 'license-verifier':
        authorized = True
    elif src == 'license-verifier' and dst == 'task-scheduler':
        authorized = True
    elif src == 'command-block' and dst == 'scada-sender' and \
            opr == 'send_message':
        authorized = True
    elif src == 'scada-sender' and dst == 'scada' and opr == 'send_message':
        authorized = True
    elif src == 'data-processor-analog' and dst == 'data-storage' and \
            opr == 'store_analog':
        authorized = True
    elif src == 'data-processor-discrete' and dst == 'data-storage' and \
            opr == 'store_discrete':
        authorized = True
    elif src == 'data-processor-analog' and dst == 'app' and \
            opr == 'store_analog':
        authorized = True
    elif src == 'data-processor-discrete' and dst == 'app' and \
            opr == 'store_discrete':
        authorized = True
    elif src == 'command-block' and dst == 'app' and opr == 'check_sensors':
        authorized = True
    elif src == 'app' and dst == 'data-verifier' and opr == 'verify':
        authorized = True
    elif src == 'task-scheduler' and dst == 'command-block' and \
            opr == 'check_sensors':
        authorized = True
    elif src == 'data-verifier' and dst == 'app' and opr in \
            ('get_data',):
        authorized = True
    elif src == 'data-verifier' and dst == 'data-storage' and opr in \
            ('get_data',):
        authorized = True
    elif src == 'app' and dst == 'data-verifier' and \
                opr in ('verify_data'):
        authorized = True
    elif src == 'data-storage' and dst == 'data-verifier' and \
                opr in ('verify_data'):
        authorized = True
    elif src == 'data-verifier' and dst == 'command-block' and \
            opr == 'send_message':
        authorized = True
    elif src == 'app-receiver' and dst == 'update-manager' and \
            opr == 'update_app':
        authorized = True
    elif src == 'update-manager' and dst == 'task-scheduler' and \
            opr == 'update_app':
        authorized = True
    elif src == 'task-scheduler' and dst == 'update-manager' and \
            opr == 'verify_app':
        authorized = True
    elif src == 'update-manager' and dst == 'app-verifier' and \
            opr == 'check_license':
        authorized = True
    elif src == 'app-verifier' and dst == 'app-storage' and \
            opr == 'get_file_content':
        authorized = True
    elif src == 'app-storage' and dst == 'app-verifier' and \
            opr == 'get_file_content':
        authorized = True
    elif src == 'license-verifier' and dst == 'task-scheduler' and \
            opr == 'update_app':
        authorized = True
    elif src == 'task-scheduler' and dst == 'app-updater' and \
            opr == 'update_settings':
        authorized = True
    elif src == 'app-updater' and dst == 'app' and \
            opr == 'update_settings':
        authorized = True
    elif src == 'task-scheduler' and dst == 'update-manager' and \
            opr == 'update_settings':
        authorized = True
    elif src == 'update-manager' and dst == 'app-updater' and \
            opr == 'update_settings':
        authorized = True
    elif src == 'app' and dst == 'command-block' and \
            opr == 'send_message':
        authorized = True
    # kea - Kafka events analyzer - an extra service for internal monitoring,
    # can only communicate with itself
    if src == 'kea' and dst == 'kea' \
            and (opr == 'self_test' or opr == 'test_param'):
        authorized = True
        
```

## Запуск приложения и тестов

### Запуск приложения

см. [инструкцию по запуску](README.md)
запуск проекта:

**chmod 777 -r modules**

**make**

### Запуск тестов

_Предполагается, что в ходе подготовки рабочего места все системные пакеты были установлены._

запуск тестов:

**make test** или **python simpe-test.py**
